/*
 * Copyright (c) 2010, Yawning <yawninglol at gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   * Neither the name of the Mew Developers nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

package yawning.mew;

/**
 * Level Dependent Values
 *
 * @author Yawning <yawninglol at gmail.com>
 */
public class LevelDep {
	@SuppressWarnings("serial")
	public class LevelNotSupportedException extends RuntimeException {
		public LevelNotSupportedException(String s) {
			super(s);
		}
	}

	protected int Level;

	protected double HitConv;		// HitR->1% Hit.
	protected double SpellHitConv;	// HitR->1% Spell Hit.
	protected double ExpConv;		// ExpR->1% Dodge/Parry.
	protected double CritConv;		// CritR->1% Crit.
	protected double HasteConv;		// HasteR->1% Haste. (Well; so much for the 1.3x buff in WotlK.)
	protected double MasteryConv;	// Mastery Rating->1 Mastery (????)

	protected int BuffAgiStr;		// Horn of Winter/Battle Shout Str/Agi

	protected int MobArmor;

	// Everything but pCritSuppression verified as of build 12319.
	protected double pBaseMiss = 0.08;
	protected double pBaseSpellMiss = 0.17;
	protected double pBaseDodge;
	protected double pCritSuppression = 0.048;
	protected double pGlance = 0.24;

	protected double baseMastery = 8.0;

	public LevelDep(int level) {
		// This used to be a nice factory class that had level specific data living in
		// level specific classes.
		//
		// Since I further want to separate class specific values off into their own
		// implementations, the former model would have been rather messy code wise.
		//
		// WTB: Multiple Inheritance.
		//

		this.Level = level;

		// Per LibStatLogic-1.1 (r103):
		//
		// For Levels >= 80
		// Rating = 1.0 (Percent) * H * RatingBase
		// H[80] = 3.2789998548530
		// H[85] = 12.805718893223
		//
		// RatingBase:
		//  Melee Hit: 9.37931
		//  Spell Hit: 8
		//  Crit: 14
		//  Haste: 10
		//  Expertise: 2.34483 (Per 1 Expertise)
		//  Mastery: 14
		//
		// XXX: When LibStatLogic's values are used, Exp and Melee Hit do not provide identical
		// gain per point due to rounding.  The difference is minor enough to not really matter.
		//

		double H;
		switch (level) {
		case 80:
			H = 3.2789998548530;
			this.pBaseDodge = 0.05625;	// Ghostcrawler says 23 expertise, testing shows 172 rating.  Go with the rating.
			this.BuffAgiStr = 155;
			this.MobArmor = 10502;	// Per: Copia (Crushridge-US) 2010/10/14 (Beast Lore on Maexxna 10 man)
			break;
		case 85:
			H = 12.805718893223;
			this.pBaseDodge = 0.065;
			this.BuffAgiStr = 549;	// B. Shout. @ 85
			this.MobArmor = 11977;	// 2010/10/18 - Chimaeron (Beast Lore) figure.
			break;
		default:
			throw new LevelNotSupportedException("Unsupported level: " + level);
		}

		this.HitConv = 9.37931 * H;		// HitR->1% Hit.
		this.SpellHitConv = 8 * H;		// HitR->1% Spell Hit.
		this.ExpConv = 2.34483 * H * 4;	// ExpR->1% Dodge/Parry.
		this.CritConv = 14 * H;			// CritR->1% Crit.
		this.HasteConv = 10 * H;		// HasteR->1% Haste.
		this.MasteryConv = 14 * H;		// Mastery Rating->1 Mastery
	}

	// Getters
	public int getBuffAgiStr() {
		return BuffAgiStr;
	}

	public double getCritConv() {
		return CritConv;
	}

	public double getExpConv() {
		return ExpConv;
	}

	public double getHasteConv() {
		return HasteConv;
	}

	public double getHitConv() {
		return HitConv;
	}

	public double getSpellHitConv() {
		return SpellHitConv;
	}

	public double getMasteryConv() {
		return MasteryConv;
	}

	public int getMobArmor() {
		return MobArmor;
	}

	public double getPBaseDodge() {
		return pBaseDodge;
	}

	public double getPBaseMiss() {
		return pBaseMiss;
	}

	public double getPBaseSpellMiss() {
		return pBaseSpellMiss;
	}

	public double getPCritSuppression() {
		return pCritSuppression;
	}

	public double getPGlance() {
		return pGlance;
	}

	public int getHitRatingCap() {
		return (int) Math.ceil(pBaseMiss * 100 * this.HitConv);
	}

	public int getExpertiseRatingCap() {
		return (int) Math.ceil(pBaseDodge * 100 * this.ExpConv);
	}

	public double getBaseMastery() {
		return baseMastery;
	}

	public double getAgiConv() {
		return 0.0;
	}
}
